package com.bskj.kuaifu.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONObject;
import com.bskj.common.bean.model.NoCarnoParkRate;
import com.bskj.common.bean.model.ParkInInfo;
import com.bskj.common.bean.model.ParkInfo;
import com.bskj.common.bean.model.ParkingLotCustomer;
import com.bskj.common.bean.model.UserCar;
import com.bskj.common.bean.model.UserCoupon;
import com.bskj.common.bean.model.UserInfo;
import com.bskj.common.bean.model.WechatTemplateMsg;
import com.bskj.common.bean.model.WxTemplateParams;
import com.bskj.common.bean.vo.CCBNoSenseParkingInReqVo;
import com.bskj.common.bean.vo.CCBNoSenseParkingOutReqVo;
import com.bskj.common.bean.vo.NoSenseParkingInReqVo;
import com.bskj.common.bean.vo.NoSenseParkingOutReqVo;
import com.bskj.common.constants.CommonConstatns;
import com.bskj.common.constants.ReturnCodeMsgConstants;
import com.bskj.common.dao.ParkInInfoDao;
import com.bskj.common.dao.ParkInfoDao;
import com.bskj.common.dao.UserCarDao;
import com.bskj.common.dao.core.BaseDao;
import com.bskj.common.dao.core.FindRequestEntity;
import com.bskj.common.dao.core.OrderEnum;
import com.bskj.common.dao.core.WhereEnum;
import com.bskj.common.enums.CouponStatusEnum;
import com.bskj.common.enums.NoSenseChannelTypeEnum;
import com.bskj.common.enums.NoSenseParkingErrorCodeEnum;
import com.bskj.common.enums.ParkChargeTypeEnum;
import com.bskj.common.service.impl.BaseServiceImpl;
import com.bskj.common.utils.DateTimeUtil;
import com.bskj.common.utils.EncryptUtil;
import com.bskj.common.utils.Global;
import com.bskj.common.utils.HttpRequestUtil;
import com.bskj.common.utils.LogUtils;
import com.bskj.common.utils.NoSensePayUtils;
import com.bskj.common.utils.StringUtils;
import com.bskj.kuaifu.bean.vo.req.ConfirmReceiveMoneyReqVo;
import com.bskj.kuaifu.bean.vo.req.GetCarNoInfoReqVo;
import com.bskj.kuaifu.bean.vo.req.OfflineDataBackupReqVo;
import com.bskj.kuaifu.bean.vo.req.ParkReqVo;
import com.bskj.kuaifu.bean.vo.resp.ParkinfoAppealVo;
import com.bskj.kuaifu.bean.vo.resp.UserMoneyLogRespVo;
import com.bskj.kuaifu.bean.vo.resp.UserParkInfoRespVo;
import com.bskj.kuaifu.bean.vo.resp.UserUnPayDetailRespVo;
import com.bskj.kuaifu.service.INoCarnoParkRateService;
import com.bskj.kuaifu.service.IParkInfoService;
import com.bskj.kuaifu.service.IParkingLotCustomerService;
import com.bskj.kuaifu.service.IUserCouponService;
import com.bskj.kuaifu.service.IUserInfoService;

@Service
public class ParkInfoServiceImpl extends BaseServiceImpl<ParkInfo> implements IParkInfoService {
	@Autowired
	private ParkInfoDao parkInfoDao;

	@Autowired
	private UserCarDao userCarDao;

	@Autowired
	private IUserInfoService userInfoService;

	@Autowired
	private IParkingLotCustomerService parkingLotCustomerService;

	@Autowired
	private IUserCouponService userCouponService;

	@Autowired
	private ParkInInfoDao parkInInfoDao;

	@Autowired
	private INoCarnoParkRateService noCarnoParkRateService;

	@Override
	public BaseDao<ParkInfo> getBaseDao() {
		return parkInfoDao;
	}

	public Map<String, Object> carOut(ParkReqVo reqVo, String ip) throws Exception {
		/*
		 * 流程：
		 *  1、计算出需要支付的金额（需要扣掉停车券），如果需要支付的金额大于0，走下面的流程
		 *  	1、调用微信无感支付平台接口 
		 *  	2、如果返回值是是支持无感支付后付费的，且支付成功的，流程走完，返回开闸信息
		 */
		Map<String, Object> resultMap = validParkReq(reqVo);
		if (ReturnCodeMsgConstants.REQUEST_INVALID.equals(resultMap.get("resultCode"))) {
			resultMap.remove("parkingLot");
			return resultMap;
		}

		if (StringUtils.isBank(reqVo.getBoxNo())) {
			reqVo.setBoxNo("默认岗亭");
		}

		//		if (checkDuplicate(reqVo)) {
		//			resultMap.put("resultCode", ReturnCodeMsgConstants.REQUEST_INVALID);
		//			resultMap.put("resultMsg", "重复的请求!");
		//			resultMap.remove("parkingLot");
		//			return resultMap;
		//		}

		// 保留停车信息
		ParkInfo parkInfo = new ParkInfo();
		parkInfo.setCarNo(reqVo.getCarNo());
		parkInfo.setBoxNo(reqVo.getBoxNo());
		parkInfo.setParkLotCustimerId(reqVo.getParkLotCustomerId());
		parkInfo.setInTime(reqVo.getInTime());
		parkInfo.setOutTime(reqVo.getOutTime());
		parkInfo.setCharge(reqVo.getCharge());
		parkInfo.setChargeType(ParkChargeTypeEnum.NOT_PAY.getKey());
		parkInfo.setCreateTime(new Date());
		parkInfo.setUpdateTime(new Date());

		parkInfo.setUserCouponId(0);
		parkInfo.setNeedPayCharge(reqVo.getCharge());

		// 如果charge为0 直接返回平台支付，返回开闸放行
		if (reqVo.getCharge() == 0) {
			parkInfo.setChargeType(ParkChargeTypeEnum.PLATFROM_PAY.getKey());
			insert(parkInfo);
			resultMap.remove("parkingLot");
			resultMap.put("parkInfoId", parkInfo.getId() + "");
			resultMap.put("resultCode", ReturnCodeMsgConstants.SYS_PAY_CODE);
			resultMap.put("resultMsg", ReturnCodeMsgConstants.SYS_PAY_MSG);
			return resultMap;
		}

		// 计算实际需要支付的金额
		ParkingLotCustomer parkLot = (ParkingLotCustomer) resultMap.get("parkingLot");
		resultMap.remove("parkingLot");
		UserInfo userInfo = userInfoService.getUserInfoByCarNo(CommonConstatns.KUAIFU_WX_APPID, reqVo.getCarNo());
		if (userInfo != null) {
			parkInfo.setUserId(getUserId(reqVo.getCarNo()));
			UserCoupon coupon = userCouponService.getValidCoupon(parkLot.getId(), userInfo.getId(), reqVo.getOutTime());
			if (coupon != null) {
				coupon.setStatus(CouponStatusEnum.used.getKey());
				coupon.setUpdateTime(new Date());
				int needPayCharge = 0;
				if (coupon.getCouponMoneyType() != null && coupon.getCouponMoneyType() == 2) {
					needPayCharge = 0;
				} else {
					needPayCharge = coupon.getMoney() > reqVo.getCharge() ? 0 : reqVo.getCharge() - coupon.getMoney();
				}
				parkInfo.setUserCouponId(coupon.getId());
				parkInfo.setNeedPayCharge(needPayCharge);
				userCouponService.update(coupon);
			}
		}

		// 如果needCharge为0 直接为平台付款，返回开闸放行
		if (parkInfo.getNeedPayCharge() == 0) {
			parkInfo.setChargeType(ParkChargeTypeEnum.PLATFROM_PAY.getKey());
			insert(parkInfo);
			resultMap.put("parkInfoId", parkInfo.getId() + "");
			resultMap.put("resultCode", ReturnCodeMsgConstants.SYS_PAY_CODE);
			resultMap.put("resultMsg", ReturnCodeMsgConstants.SYS_PAY_MSG);

			if (userInfo != null && !StringUtils.isBank(userInfo.getOpenid())) {
				try {
					sendUserMsg(userInfo.getOpenid(), CommonConstatns.KUAIFU_WX_APPID, parkLot.getName(), parkInfo);
				} catch (Exception e) {
					//推送模板消息失败 不影响业务逻辑
					LogUtils.error("推送模板消息失败：parkInfoId : " + parkInfo.getId());
				}
			}

			return resultMap;
		}

		insert(parkInfo);
		resultMap.put("parkInfoId", parkInfo.getId() + "");

		// 调用微信的无感支付平台
		resultMap = noSenseCarOut(parkLot, parkInfo, ip);
		resultMap.put("charge", parkInfo.getNeedPayCharge() / 10);
		return resultMap;
	}

	public Map<String, Object> carIn(GetCarNoInfoReqVo reqVo) throws Exception {
		if (reqVo.getInTime() == null) {
			reqVo.setInTime(new Date());
		}
		Map<String, Object> resultMap = parkingLotCustomerService.validParkLot(reqVo.getParkLotCustomerId(),
				reqVo.getUuid());
		if (ReturnCodeMsgConstants.REQUEST_INVALID.equals(resultMap.get("resultCode"))) {
			resultMap.remove("parkingLot");
			return resultMap;
		}
		/*
		 * 流程 1、判断是否为重复数据，如果是忽略，如果不是往下走 2、调用微信的无感进场 3、如果该用户
		 * 开通了无感，可以获取该用户在公众号下的openid，用户信息入库 4、如果用户没开通无感，忽略
		 */
		ParkingLotCustomer parkLot = (ParkingLotCustomer) resultMap.get("parkingLot");
		resultMap.remove("parkingLot");

		if (!checkParkInData(reqVo)) {
			resultMap.put("resultCode", ReturnCodeMsgConstants.REQUEST_INVALID);
			resultMap.put("resultMsg", "重复的数据");
			return resultMap;
		}
		if (StringUtils.isBank(reqVo.getBoxNo())) {
			reqVo.setBoxNo("默认岗亭");
		}
		// 保存进场信息
		ParkInInfo inInfo = new ParkInInfo();
		inInfo.setBoxNo(reqVo.getBoxNo());
		inInfo.setCarNo(reqVo.getCarNo());
		inInfo.setInTime(reqVo.getInTime());
		inInfo.setParkLotCustimerId(reqVo.getParkLotCustomerId());
		inInfo.setCreateTime(new Date());
		inInfo.setUpdateTime(new Date());
		parkInInfoDao.insert(inInfo);

		//车场没有appId不支持无感支付
		if (StringUtils.isBank(parkLot.getAppid())) {
			resultMap.put("resultCode", ReturnCodeMsgConstants.NOT_SYS_USER_CODE);
			resultMap.put("resultMsg", ReturnCodeMsgConstants.NOT_SYS_USER_MSG);
			return resultMap;
		}

		// 获取免费停车时长
		int freeTime = 0;
		NoCarnoParkRate noCarnoParkRate = noCarnoParkRateService.getNoCarnoParkRate(reqVo.getParkLotCustomerId());
		if (noCarnoParkRate != null) {
			if (noCarnoParkRate.getStegeOneRate() == 0) {
				freeTime = new Double(noCarnoParkRate.getStegeOneTime() * 60 * 60).intValue();
			}
		}

		Map<String, Object> responMap = new HashMap<>();
		if (NoSenseChannelTypeEnum.CCB.getKey().equals(parkLot.getNoSenseType())) {
			//建行无感
			CCBNoSenseParkingInReqVo inReqVo = new CCBNoSenseParkingInReqVo(parkLot.getAppid(), parkLot.getMchId(),
					parkLot.getParkingName(), reqVo.getCarNo(),
					DateTimeUtil.date2String(reqVo.getInTime(), "yyyyMMddHHmmss"), freeTime + "", parkLot.getSignType(),
					parkLot.getSign());

			responMap = NoSensePayUtils.JHParkIn(inReqVo);

			LogUtils.debug("JH nosense in respone : " + responMap);
		} else {
			//微信或者支付宝无感
			NoSenseParkingInReqVo inReq = new NoSenseParkingInReqVo(parkLot.getAppid(), parkLot.getNoSenseType(),
					parkLot.getSignType(), parkLot.getSign());
			inReq.setTradeScene("PARKING");
			inReq.setStartTime(DateTimeUtil.date2String(reqVo.getInTime(), "yyyyMMddHHmmss"));
			inReq.setPlateNumber(reqVo.getCarNo());
			inReq.setCarType("小型车");
			inReq.setFreeTime(freeTime + "");
			inReq.setMchId(parkLot.getMchId());
			inReq.setParkingName(parkLot.getParkingName());
			inReq.setNotifyUrl("https://kuaifu.boshukeji.com/pay/noSenseNotify");

			// 调用微信的无感支付平台
			responMap = NoSensePayUtils.parkIn(inReq);

			LogUtils.debug("nosense in respone : " + responMap);
			String errorCode = "";
			if(responMap != null && responMap.get("code") != null) {
				errorCode = (String) responMap.get("code");
			}
			if (NoSenseParkingErrorCodeEnum.VEHICLE_NOT_EXIST.getKey().equals(errorCode)) {
				// 如果车牌没绑定
				resultMap.put("resultCode", ReturnCodeMsgConstants.NOT_SYS_USER_CODE);
				resultMap.put("resultMsg", ReturnCodeMsgConstants.NOT_SYS_USER_MSG);
			} else {
				if ((boolean) responMap.get("result")) {
					String data = EncryptUtil.deBase64((String) responMap.get("data"));
					LogUtils.debug("nosense in respone data: " + data);
				}
			}
		}

		return resultMap;
	}

	@Override
	public Map<String, Object> confirmReceiveMoney(ConfirmReceiveMoneyReqVo reqVo, String ip) throws Exception {
		// 理论上讲，一个停车场一次性只会操作一单数据，用uuid作为锁应该没问题!（待验证~）
		Map<String, Object> resultMap = validconfirmReceiveMoneyReq(reqVo);
		synchronized (reqVo.getUuid()) {
			if (ReturnCodeMsgConstants.REQUEST_INVALID.equals(resultMap.get("resultCode"))) {
				resultMap.remove("parkingLot");
				return resultMap;
			}

			ParkInfo parkInfo = get(reqVo.getParkInfoId());
			// 校验是否为重复请求或者非法的请求
			if (ParkChargeTypeEnum.NOT_PAY.getKey() != parkInfo.getChargeType()) {
				// 该停车费记录已经处理
				if (parkInfo.getChargeType() == reqVo.getChargeType()) {
					// 如果是请求的数据和处理后的数据匹配，认为是重复请求（或者是），返回处理完成结果
					resultMap.remove("parkingLot");
					resultMap.put("resultCode", ReturnCodeMsgConstants.SUCCESS_CODE);
					resultMap.put("resultMsg", ReturnCodeMsgConstants.SUCCESS_MSG);
					return resultMap;
				} else {
					resultMap.remove("parkingLot");
					resultMap.put("resultCode", ReturnCodeMsgConstants.REQUEST_INVALID);
					resultMap.put("resultMsg", "该单已经处理完成！");
					return resultMap;
				}
			}

			ParkingLotCustomer parkLot = (ParkingLotCustomer) resultMap.get("parkingLot");
			resultMap.remove("parkingLot");

			/*
			 * 确认支付 1、如果确认为现金支付。更新停车记录 2、如果确认为平台代扣
			 */
			UserInfo userInfo = userInfoService.getUserInfoByCarNo(parkLot.getAppid(), parkInfo.getCarNo());
			if (ParkChargeTypeEnum.CASH_PAY.getKey() == reqVo.getChargeType()) {
				// 现金支付
				if (userInfo != null) {
					parkInfo.setUserId(getUserId(parkInfo.getCarNo()));
					parkInfo.setUpdateTime(new Date());
				}
				parkInfo.setChargeType(ParkChargeTypeEnum.CASH_PAY.getKey());
				update(parkInfo);
				resultMap.put("resultCode", ReturnCodeMsgConstants.SUCCESS_CODE);
				resultMap.put("resultMsg", ReturnCodeMsgConstants.SUCCESS_MSG);
			} else {
				// 平台代扣
				/*
				 * 再次调用微信无感，然后处理结果
				 */
				resultMap = noSenseCarOut(parkLot, parkInfo, ip);
			}
			return resultMap;
		}
	}

	/**
	 * 校验停车收费入参的合法性
	 *
	 * @param reqVo
	 * @return
	 * @throws Exception
	 */
	private Map<String, Object> validParkReq(ParkReqVo reqVo) throws Exception {
		Map<String, Object> resultMap = new HashMap<>();
		if (reqVo.getCharge() < 0) {
			resultMap.put("resultCode", ReturnCodeMsgConstants.REQUEST_INVALID);
			resultMap.put("resultMsg", "支付金额不合法!");
			return resultMap;
		}

		resultMap = parkingLotCustomerService.validParkLot(reqVo.getParkLotCustomerId(), reqVo.getUuid());

		return resultMap;
	}

	/**
	 * 校验确认收费入参是否合法
	 *
	 * @param reqVo
	 * @return
	 * @throws Exception
	 */
	private Map<String, Object> validconfirmReceiveMoneyReq(ConfirmReceiveMoneyReqVo reqVo) throws Exception {
		Map<String, Object> resultMap = new HashMap<>();

		if (ParkChargeTypeEnum.get(reqVo.getChargeType()) == null
				|| ParkChargeTypeEnum.NOT_PAY.getKey() == reqVo.getChargeType()) {
			resultMap.put("resultCode", ReturnCodeMsgConstants.REQUEST_INVALID);
			resultMap.put("resultMsg", "支付类型不合法!");
			return resultMap;
		}

		ParkInfo parkInfo = get(reqVo.getParkInfoId());
		if (parkInfo == null) {
			resultMap.put("resultCode", ReturnCodeMsgConstants.REQUEST_INVALID);
			resultMap.put("resultMsg", "停车记录不存在!");
			return resultMap;
		}

		resultMap = parkingLotCustomerService.validParkLot(reqVo.getParkLotCustomerId(), reqVo.getUuid());

		return resultMap;
	}

	public List<UserParkInfoRespVo> getUserParkInfo(int userId, Integer lastParkInfoId) throws Exception {
		FindRequestEntity findParkInfoReqEntity = new FindRequestEntity();
		findParkInfoReqEntity.addWhere("user_id", WhereEnum.EQ, userId);
		if (lastParkInfoId != null && lastParkInfoId != 0) {
			findParkInfoReqEntity.addWhere("id", WhereEnum.LT, lastParkInfoId);
		}

		findParkInfoReqEntity.addOrder("id", OrderEnum.DESC);
		findParkInfoReqEntity.setPage(1, CommonConstatns.DEFAULT_PAGE_SZIE);

		List<ParkInfo> parkInfoList = find(findParkInfoReqEntity);

		List<UserParkInfoRespVo> resultList = new ArrayList<UserParkInfoRespVo>();
		if (parkInfoList != null && parkInfoList.size() > 0) {
			for (ParkInfo parkInfo : parkInfoList) {
				UserParkInfoRespVo respVo = new UserParkInfoRespVo();
				BeanUtils.copyProperties(parkInfo, respVo);

				// 完善停车场信息
				fullParkInfo(respVo);
				resultList.add(respVo);
			}
		}
		return resultList;
	}

	public UserUnPayDetailRespVo getUnPayDetail(int userId) throws Exception {
		UserUnPayDetailRespVo respVo = new UserUnPayDetailRespVo();
		UserInfo userInfo = userInfoService.get(userId);
		if (userInfo == null) {
			return null;
		} else {
			if (userInfo.getMoney() >= 0) {
				return respVo;
			} else {
				// 平台代扣后余额小于0,支付前余额不小于0的最后一笔停车单，之后所有支付金额大于0，余额小于0的都为欠费单
				FindRequestEntity findParkInfoReqEntity = new FindRequestEntity();
				findParkInfoReqEntity.addWhere("user_id", WhereEnum.EQ, userId);
				findParkInfoReqEntity.addWhere("change_money", WhereEnum.GT, 0);
				findParkInfoReqEntity.addWhere("before_money", WhereEnum.GE, 0);
				findParkInfoReqEntity.addWhere("after_money", WhereEnum.LT, 0);
				findParkInfoReqEntity.addWhere("charge_type", WhereEnum.EQ, ParkChargeTypeEnum.PLATFROM_PAY.getKey());
				findParkInfoReqEntity.addOrder("create_time", OrderEnum.DESC);
				findParkInfoReqEntity.setPage(1, 1);
				List<ParkInfo> parkInfoList = find(findParkInfoReqEntity);
				if (parkInfoList != null && parkInfoList.size() > 0) {
					ParkInfo parkInfo = parkInfoList.get(0);

					findParkInfoReqEntity = new FindRequestEntity();
					findParkInfoReqEntity.addWhere("user_id", WhereEnum.EQ, userId);
					findParkInfoReqEntity.addWhere("change_money", WhereEnum.GT, 0);
					findParkInfoReqEntity.addWhere("after_money", WhereEnum.LT, 0);
					findParkInfoReqEntity.addWhere("id", WhereEnum.GE, parkInfo.getId());
					findParkInfoReqEntity.addWhere("charge_type", WhereEnum.EQ,
							ParkChargeTypeEnum.PLATFROM_PAY.getKey());
					findParkInfoReqEntity.addOrder("create_time", OrderEnum.DESC);
					List<ParkInfo> qfParkList = find(findParkInfoReqEntity);
					List<UserParkInfoRespVo> arrearsParkInfoList = new ArrayList<UserParkInfoRespVo>();
					if (qfParkList != null && qfParkList.size() > 0) {
						for (ParkInfo qfParkInfo : qfParkList) {
							UserParkInfoRespVo parkInfoRespVo = new UserParkInfoRespVo();
							BeanUtils.copyProperties(qfParkInfo, parkInfoRespVo);

							// 完善停车场信息
							fullParkInfo(parkInfoRespVo);
							arrearsParkInfoList.add(parkInfoRespVo);
						}
						respVo.setArrearsParkInfoList(arrearsParkInfoList);
					}
				}

				// 未支付的订单
				FindRequestEntity findUnPayParkInfoReqEntity = new FindRequestEntity();
				findUnPayParkInfoReqEntity.addWhere("user_id", WhereEnum.EQ, userId);
				findUnPayParkInfoReqEntity.addWhere("charge_type", WhereEnum.EQ, ParkChargeTypeEnum.NOT_PAY.getKey());
				findUnPayParkInfoReqEntity.addOrder("create_time", OrderEnum.DESC);
				List<ParkInfo> unPayParkInfoList = find(findUnPayParkInfoReqEntity);
				List<UserParkInfoRespVo> unPayParkInfoRespList = new ArrayList<UserParkInfoRespVo>();
				if (unPayParkInfoList != null && unPayParkInfoList.size() > 0) {
					for (ParkInfo parkInfo : unPayParkInfoList) {
						UserParkInfoRespVo parkInfoRespVo = new UserParkInfoRespVo();
						BeanUtils.copyProperties(parkInfo, parkInfoRespVo);

						// 完善停车场信息
						fullParkInfo(parkInfoRespVo);
						unPayParkInfoRespList.add(parkInfoRespVo);
					}
					respVo.setUnPayParkInfoList(unPayParkInfoRespList);
				}
				return respVo;
			}
		}
	}

	private void fullParkInfo(UserParkInfoRespVo userParkInfoRespVo) throws Exception {
		ParkingLotCustomer parkingLot = parkingLotCustomerService.get(userParkInfoRespVo.getParkLotCustimerId());
		if (parkingLot != null) {
			userParkInfoRespVo.setParkLotName(parkingLot.getName());
			userParkInfoRespVo.setParkLotArea(parkingLot.getAreaName() + "  " + parkingLot.getStree());
		}
	}

	@Override
	public ParkInfo getParkInfo(String outTradeNo) throws Exception {
		FindRequestEntity findReqEntity = new FindRequestEntity();
		findReqEntity.addWhere("out_trade_no", WhereEnum.EQ, outTradeNo);
		List<ParkInfo> parkInfo = find(findReqEntity);
		if (parkInfo != null && parkInfo.size() > 0) {
			return parkInfo.get(0);
		}
		return null;
	}

	private Map<String, Object> noSenseCarOut(ParkingLotCustomer parkLot, ParkInfo parkInfo, String ip)
			throws Exception {
		Map<String, Object> resultMap = new HashMap<>();
		resultMap.put("parkInfoId", parkInfo.getId() + "");

		//车场没有appId不支持无感支付
		if (StringUtils.isBank(parkLot.getAppid())) {
			resultMap.put("resultCode", ReturnCodeMsgConstants.NOT_SYS_USER_CODE);
			resultMap.put("resultMsg", ReturnCodeMsgConstants.NOT_SYS_USER_MSG);
			return resultMap;
		}

		// 如果车牌号码为空 直接返回为非注册用户
		if (StringUtils.isBank(parkInfo.getCarNo())) {
			resultMap.put("resultCode", ReturnCodeMsgConstants.NOT_SYS_USER_CODE);
			resultMap.put("resultMsg", ReturnCodeMsgConstants.NOT_SYS_USER_MSG);
			return resultMap;
		}

		if (NoSenseChannelTypeEnum.CCB.getKey().equals(parkLot.getNoSenseType())) {
			//建行无感
			CCBNoSenseParkingOutReqVo outReqVo = new CCBNoSenseParkingOutReqVo(parkLot.getAppid(), parkLot.getMchId(),
					parkLot.getParkingName(), (parkInfo.getNeedPayCharge() * 10) + "",
					"https://kuaifu.boshukeji.com/pay/noSenseNotify",
					DateTimeUtil.date2String(parkInfo.getInTime(), "yyyyMMddHHmmss"),
					DateTimeUtil.date2String(parkInfo.getOutTime(), "yyyyMMddHHmmss"), parkInfo.getCarNo(),
					parkLot.getName(), parkLot.getSignType(), parkLot.getSign());

			Map<String, Object> responMap = NoSensePayUtils.JHParkOut(outReqVo);

			LogUtils.debug("JH nosense out respone : " + responMap);
			
			JSONObject data = JSONObject.parseObject(responMap.get("data").toString());
			String isAllow = data.getString("is_allow");
			
			if ("SUCCESS".equals(isAllow))  {
				// 可以抬杆放行,更新支付信息
				parkInfo.setChargeType(ParkChargeTypeEnum.PLATFROM_PAY.getKey());
				resultMap.put("resultCode", ReturnCodeMsgConstants.SYS_PAY_CODE);
				resultMap.put("resultMsg", ReturnCodeMsgConstants.SYS_PAY_MSG);

				UserInfo userInfo = userInfoService.get(parkInfo.getUserId());
				if (userInfo != null && !StringUtils.isBank(userInfo.getOpenid())) {
					try {
						sendUserMsg(userInfo.getOpenid(), CommonConstatns.KUAIFU_WX_APPID, parkLot.getName(),
								parkInfo);
					} catch (Exception e) {
						//推送模板消息失败 不影响业务逻辑
						LogUtils.error("推送模板消息失败：parkInfoId : " + parkInfo.getId());
					}
				}
			} else {
				// 不能放行
				resultMap.put("resultCode", ReturnCodeMsgConstants.NOT_SYS_USER_CODE);
				resultMap.put("resultMsg", ReturnCodeMsgConstants.NOT_SYS_USER_MSG);
			}
		} else {
			NoSenseParkingOutReqVo outReq = new NoSenseParkingOutReqVo(parkLot.getAppid(), parkLot.getNoSenseType(),
					parkLot.getSignType(), parkLot.getSign());
			// outReq.setAmount("1");
			outReq.setAmount((parkInfo.getNeedPayCharge() * 10) + "");
			outReq.setClientIp(ip);
			outReq.setMchId(parkLot.getMchId());
			outReq.setTradeScene("PARKING");
			outReq.setStartTime(DateTimeUtil.date2String(parkInfo.getInTime(), "yyyyMMddHHmmss"));
			outReq.setEndTime(DateTimeUtil.date2String(parkInfo.getOutTime(), "yyyyMMddHHmmss"));
			outReq.setPlateNumber(parkInfo.getCarNo());
			outReq.setCarType("小型车");
			outReq.setParkingName(parkLot.getParkingName());
			outReq.setNotifyUrl("https://kuaifu.boshukeji.com/pay/noSenseNotify");
			Map<String, Object> responMap = NoSensePayUtils.parkOut(outReq);
			LogUtils.debug("nosense out respone : " + responMap);
			String errorCode = "";
			if(responMap != null && responMap.get("code") != null) {
				errorCode = (String) responMap.get("code");
			}
			Object dataObj = responMap.get("data");
			String resultStr = "";
			if (dataObj != null && !"".equals(dataObj)) {
				String data = EncryptUtil.deBase64((String) responMap.get("data"));
				JSONObject dataJson = JSONObject.parseObject(data);
				LogUtils.debug("nosense out respone data: " + dataJson);
				resultStr = dataJson.getString("isAllow");
				String outTradeNo = dataJson.getString("outTradeNo");
				parkInfo.setOutTradeNo(outTradeNo);
			}

			if (NoSenseParkingErrorCodeEnum.VEHICLE_NOT_EXIST.getKey().equals(errorCode)) {
				// 如果车牌没绑定
				resultMap.put("resultCode", ReturnCodeMsgConstants.NOT_SYS_USER_CODE);
				resultMap.put("resultMsg", ReturnCodeMsgConstants.NOT_SYS_USER_MSG);
			} else if (NoSenseParkingErrorCodeEnum.REQUEST_BLOCKED.getKey().equals(errorCode)) {
				// 如果用户不符合免密规则
				resultMap.put("resultCode", ReturnCodeMsgConstants.USER_ARREAR_CODE);
				resultMap.put("resultMsg", ReturnCodeMsgConstants.USER_ARREAR_MSG);
			} else {
				if ((boolean) responMap.get("result")) {
					if ("SUCCESS".equals(resultStr)) {
						// 可以抬杆放行,更新支付信息
						parkInfo.setChargeType(ParkChargeTypeEnum.PLATFROM_PAY.getKey());
						resultMap.put("resultCode", ReturnCodeMsgConstants.SYS_PAY_CODE);
						resultMap.put("resultMsg", ReturnCodeMsgConstants.SYS_PAY_MSG);

						UserInfo userInfo = userInfoService.get(parkInfo.getUserId());
						if (userInfo != null && !StringUtils.isBank(userInfo.getOpenid())) {
							try {
								sendUserMsg(userInfo.getOpenid(), CommonConstatns.KUAIFU_WX_APPID, parkLot.getName(),
										parkInfo);
							} catch (Exception e) {
								//推送模板消息失败 不影响业务逻辑
								LogUtils.error("推送模板消息失败：parkInfoId : " + parkInfo.getId());
							}
						}
					} else {
						// 不能放行
						resultMap.put("resultCode", ReturnCodeMsgConstants.NOT_SYS_USER_CODE);
						resultMap.put("resultMsg", ReturnCodeMsgConstants.NOT_SYS_USER_MSG);
					}
				} else {
					resultMap.put("resultCode", ReturnCodeMsgConstants.USER_ARREAR_CODE);
					resultMap.put("resultMsg", ReturnCodeMsgConstants.USER_ARREAR_MSG);
				}
			}
		}
		update(parkInfo);
		return resultMap;
	}

	@Override
	public List<UserMoneyLogRespVo> getUserMoneyLog(Integer userId, Integer page, Integer pageSize) throws Exception {
		List<UserMoneyLogRespVo> userMoneyLogRespVoList = new ArrayList<>();
		if (page == null || page == 0) {
			page = 1;
		}
		if (pageSize == null || pageSize == 0) {
			pageSize = CommonConstatns.DEFAULT_PAGE_SZIE;
		}
		FindRequestEntity findRequestEntity = new FindRequestEntity();
		findRequestEntity.addWhere("user_id", WhereEnum.EQ, userId);
		findRequestEntity.addOrder("create_time", OrderEnum.DESC);
		findRequestEntity.setPage(page, pageSize);
		List<ParkInfo> parkInfoList = find(findRequestEntity);
		if (parkInfoList == null || parkInfoList.size() == 0) {
			return null;
		}
		for (ParkInfo parkInfo : parkInfoList) {
			UserMoneyLogRespVo userMoneyLogRespVo = new UserMoneyLogRespVo();
			userMoneyLogRespVo.setId(parkInfo.getId());
			userMoneyLogRespVo.setCarNo(parkInfo.getCarNo());
			userMoneyLogRespVo.setOutTime(DateTimeUtil.date2String(parkInfo.getOutTime()));
			userMoneyLogRespVo.setBeforeMoney(parkInfo.getCharge());
			if (parkInfo.getUserCouponId() == 0) {
				userMoneyLogRespVo.setAfterCoupon(0);
			} else {
				userMoneyLogRespVo.setAfterCoupon(userCouponService.get(parkInfo.getUserCouponId()).getMoney());
			}
			userMoneyLogRespVo
					.setParkLotName(parkingLotCustomerService.get(parkInfo.getParkLotCustimerId()).getParkingName());
			userMoneyLogRespVo.setAfterMoney(parkInfo.getNeedPayCharge());
			userMoneyLogRespVoList.add(userMoneyLogRespVo);
		}
		return userMoneyLogRespVoList;
	}

	//	private boolean checkDuplicate(ParkReqVo reqVo) throws Exception {
	//		FindRequestEntity findReqParam = new FindRequestEntity();
	//		findReqParam.addWhere("car_no", WhereEnum.EQ, reqVo.getCarNo());
	//		findReqParam.addWhere("park_lot_custimer_id", WhereEnum.EQ, reqVo.getParkLotCustomerId());
	//		findReqParam.addWhere("in_time", WhereEnum.EQ, reqVo.getInTime());
	//		findReqParam.addWhere("out_time", WhereEnum.EQ, reqVo.getOutTime());
	//		List<ParkInfo> parkInfoList = find(findReqParam);
	//		if (parkInfoList != null && parkInfoList.size() > 0) {
	//			return true;
	//		}
	//		return false;
	//	}

	private boolean checkParkInData(GetCarNoInfoReqVo reqVo) throws Exception {
		FindRequestEntity findReq = new FindRequestEntity();
		findReq.addWhere("car_no", WhereEnum.EQ, reqVo.getCarNo());
		findReq.addWhere("park_lot_custimer_id", WhereEnum.EQ, reqVo.getParkLotCustomerId());
		findReq.addWhere("in_time", WhereEnum.EQ, reqVo.getInTime());
		int count = parkInInfoDao.count(findReq.getWhereList());
		if (count > 0) {
			return false;
		}
		return true;
	}

	@Override
	public void checkOfflineData(OfflineDataBackupReqVo reqVo) throws Exception {
		/*
		 * TODO 离线数据的处理暂时不考虑停车券问题
		 * 
		 * 离线数据处理 1、在t_park_info表中查询和离线数据一样的记录 2、如果有
		 * a、charge_type为未付款（0），将charge_type改为现金支付（1）。end。
		 * b、如果charge_type不为未付款（0），忽略这条记录。end。 3、如果没有
		 * a、插入这条记录，并且charge_type为现金支付（1）。end
		 */
		if (StringUtils.isBank(reqVo.getBoxNo())) {
			reqVo.setBoxNo("默认岗亭");
		}

		// step1,查询记录
		FindRequestEntity findReqParam = new FindRequestEntity();
		findReqParam.addWhere("car_no", WhereEnum.EQ, reqVo.getCarNo());
		findReqParam.addWhere("park_lot_custimer_id", WhereEnum.EQ, reqVo.getParkLotCustomerId());
		findReqParam.addWhere("in_time", WhereEnum.EQ, reqVo.getInTime());
		findReqParam.addWhere("out_time", WhereEnum.EQ, reqVo.getOutTime());
		findReqParam.addWhere("charge", WhereEnum.EQ, reqVo.getCharge());
		List<ParkInfo> parkInfoList = find(findReqParam);
		if (parkInfoList != null && parkInfoList.size() > 0) {
			// step2 如果有记录
			ParkInfo parkInfo = parkInfoList.get(0);
			if (ParkChargeTypeEnum.NOT_PAY.getKey() == parkInfo.getChargeType()) {
				// charge_type为0
				parkInfo.setChargeType(ParkChargeTypeEnum.CASH_PAY.getKey());
				parkInfo.setIsOfflineData(1);
				parkInfo.setUpdateTime(new Date());
				update(parkInfo);
			} else {
				// charge_type不为0，暂时不处理
			}
		} else {
			// step3 没有这条记录，插入这条记录
			ParkInfo parkInfo = new ParkInfo();
			parkInfo.setCarNo(reqVo.getCarNo());
			parkInfo.setBoxNo(reqVo.getBoxNo());
			parkInfo.setParkLotCustimerId(reqVo.getParkLotCustomerId());
			parkInfo.setInTime(reqVo.getInTime());
			parkInfo.setOutTime(reqVo.getOutTime());
			parkInfo.setCharge(reqVo.getCharge());
			parkInfo.setUserId(getUserId(reqVo.getCarNo()));
			parkInfo.setUserCouponId(0);
			parkInfo.setNeedPayCharge(reqVo.getCharge());
			parkInfo.setChargeType(ParkChargeTypeEnum.CASH_PAY.getKey());
			parkInfo.setIsOfflineData(1);
			parkInfo.setCreateTime(new Date());
			parkInfo.setUpdateTime(new Date());
			insert(parkInfo);
		}
	}

	private Integer getUserId(String carNo) throws Exception {
		FindRequestEntity findReq = new FindRequestEntity();
		findReq.addWhere("car_no", WhereEnum.EQ, carNo);
		findReq.addWhere("appid", WhereEnum.EQ, CommonConstatns.KUAIFU_WX_APPID);
		List<UserCar> userCars = userCarDao.find(findReq);
		if (userCars != null && userCars.size() > 0) {
			return userCars.get(0).getUserId();
		}
		/*
		 * 根据固定的appId以及车牌号查找在慧泊客中绑定过车牌的车主id
		 */
		return null;
	}

	@Override
	public ParkinfoAppealVo getParkinfoAppealVo(Integer id) throws Exception {
		ParkInfo parkInfo = parkInfoDao.get(id);
		ParkingLotCustomer parkingLotCustomer = parkingLotCustomerService.get(parkInfo.getParkLotCustimerId());
		ParkinfoAppealVo parkinfoAppealVo = new ParkinfoAppealVo();
		return parkinfoAppealVo.setParinfoAppealVo(parkInfo, parkingLotCustomer);
	}

	private static void sendUserMsg(String openId, String appid, String parkCustomerName, ParkInfo parkInfo)
			throws Exception {
		int money = parkInfo.getCharge() / 10; //应付金额
		int needPayMoney = parkInfo.getNeedPayCharge() / 10;// 实在扣金额
		int couponMoney = money - needPayMoney; //停车券抵扣的金额

		String tempMsgId = "Eac5lMlvGUzLgouBch9s4eqFkqbR7PpbqHpU1ttGkas";
		WechatTemplateMsg tempMsg = new WechatTemplateMsg();
		tempMsg.setTemplate_id(tempMsgId);
		tempMsg.setTouser(openId);
		WxTemplateParams dataParams = new WxTemplateParams();
		dataParams.put("first", "您好，您通过慧泊客无感支付自动支付了一笔停车费用");
		dataParams.put("keyword1", parkCustomerName);
		dataParams.put("keyword2", parkInfo.getCarNo());
		dataParams.put("keyword3", DateTimeUtil.getDisBetweenTimes(parkInfo.getInTime(), parkInfo.getOutTime()));
		dataParams.put("keyword4", money + ".00元");
		if (couponMoney > 0) {
			dataParams.put("keyword5", needPayMoney + ".00元 （停车券抵用" + couponMoney + ".00元）");
		} else {
			dataParams.put("keyword5", needPayMoney + ".00元");
		}
		tempMsg.setData(dataParams);
		String WX_SEND_TEMPLATE_URL = Global.getConfig("WX_SEND_TEMPLATE_URL");
		String jsonData = JSONObject.toJSONString(tempMsg);
		Map<String, Object> params = new HashMap<>();
		params.put("jsonData", jsonData);
		params.put("appId", appid);
		System.out.println(HttpRequestUtil.httpClientGet(WX_SEND_TEMPLATE_URL, params));
	}

	public static void main(String[] args) throws Exception {
		ParkInfo parkInfo = new ParkInfo();
		parkInfo.setCarNo("湘G1921");
		parkInfo.setInTime(DateTimeUtil.string2Date("2018-08-06 00:00:00"));
		parkInfo.setOutTime(new Date());
		parkInfo.setCharge(200);
		parkInfo.setNeedPayCharge(200);
		sendUserMsg("ouUoA1jVIk0121cNfR21hw8zNCyI", "wxa5337aa97b8fea09", "泊数科技停车场", parkInfo);
	}
}
